package com.siteseat.crudeq.client;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import com.siteseat.common.misc.TimeHelper;
import com.siteseat.crudeq.common.raw.MessageHelper;
import com.siteseat.crudeq.common.raw.Constants.MESSAGE;

public class ClientMessage {
  
  public static ClientMessage STOPPED = new ClientMessage();
  
  public static List<ClientMessage> STOPPED_LIST = Collections.unmodifiableList( new ArrayList<ClientMessage>(0) );

  private Integer    queueId;

  private long   receiveTimestamp;

  private long   chunkId;

  private int    payloadLocalOffset;
  
  private int    payloadBase;// offset to payload[]

  private byte[] payload;
  
  /**
   *
   *
   */
  public ClientMessage() {
    this.receiveTimestamp = System.currentTimeMillis();
  }
  
  /**
   * {@inheritDoc}
   */
  @Override
  public String toString() {
    return "{queueId=" + getQueueId() + ", receiveTimestamp=" + TimeHelper.format( getReceiveTimestamp() ) 
          + ", chunkId=" + getChunkId() + ", payloadLocalOffset=" + getPayloadLocalOffset() 
          + ", payloadBase=" + getPayloadBase() + "}";
  }
  
  /**
   * 
   *
   * @return
   */
  public boolean isValid() {
    return MessageHelper.isValidMagic( getPayload(), getPayloadLocalOffset() );
  }

  /**
   * Gets the payloadSize
   * 
   * @return the payloadSize
   */
  public int getPayloadSize() {
    return MessageHelper.readSize( getPayload(), getPayloadLocalOffset() );
  }
  
  /**
   * Gets the payloadSize
   * 
   * @return the payloadSize
   */
  public int getContentSize() {
    return getPayloadSize() - MESSAGE.HEADER_SIZE;
  }


  /**
   * Gets the queueId
   * 
   * @return the queueId
   */
  public Integer getQueueId() {
    return queueId;
  }

  /**
   * Sets the queueId
   * 
   * @param queueId
   *          the queueId to set
   */
  public void setQueueId( Integer queueId ) {
    this.queueId = queueId;
  }

  /**
   * Gets the sentTimestamp
   * 
   * @return the sentTimestamp
   */
  public long getSentTimestamp() {
    return MessageHelper.readTimestamp( getPayload(), getPayloadLocalOffset() );
  }
  
  /**
   *
   * @return
   */
  public boolean isCommited() {
    return MessageHelper.isCommited( getSentTimestamp() );
  }

  /**
   * Gets the receiveTimestamp
   * 
   * @return the receiveTimestamp
   */
  public long getReceiveTimestamp() {
    return receiveTimestamp;
  }


  /**
   * Gets the chunkId
   * 
   * @return the chunkId
   */
  public long getChunkId() {
    return chunkId;
  }

  /**
   * Sets the chunkId
   * 
   * @param chunkId
   *          the chunkId to set
   */
  public void setChunkId( long chunkId ) {
    this.chunkId = chunkId;
  }

  /**
   * Gets the payloadBase
   * 
   * @return the payloadBase
   */
  public int getPayloadBase() {
    return payloadBase;
  }

  /**
   * Sets the payloadBase
   *
   * @param payloadBase the payloadBase to set
   */
  public void setPayloadBase( int payloadBase ) {
    this.payloadBase = payloadBase;
  }

  /**
   * Gets the payload
   * 
   * @return the payload
   */
  public byte[] getPayload() {
    return payload;
  }
//  
//  public boolean hasPayload() {
//    return getPayload() != null;
//  }

  /**
   * Sets the payload
   * 
   * @param payload
   *          the payload to set
   */
  public void setPayload( int payloadLocalOffset, byte[] payload ) {
    this.payloadLocalOffset = payloadLocalOffset;
    this.payload = payload;
  }
  
  /**
   * 
   */
//  public void clearPayload() {
//    this.payloadStart = 0;
//    this.payload = null;
//    this.contentOffset = 0;
//    this.sentTimestamp = 0;
//  }

  /**
   */
  public int getContentLocalOffset() {
    return getPayloadLocalOffset() + MESSAGE.HEADER_SIZE;
  }

  /**
   * Gets the payloadLocalOffset
   *
   * @return the payloadLocalOffset
   */
  public int getPayloadLocalOffset() {
    return payloadLocalOffset;
  }
  
  public int getNextPayloadBase() {
    return getPayloadBase() + getPayloadLocalOffset() + getPayloadSize();
  }
  
}
